﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using Xunit;

namespace Serious.SweetConfig.Tests
{
    public class ParameterListBuilderTest
    {
		private const string XML_EMPTYPARAMETERS =	"<parameters></parameters>";
		private const string XML_EMPTYENVIRONMENTS = "<parameters></parameters>";

		[Fact]
		public void BuildParameterList_WithNullParameterXmlDoc_ThrowsArgumentNullException()
		{
			var exception = Assert.Throws<ArgumentNullException>(
			delegate
			{
				new ParameterListBuilder().BuildParameterList(null, XDocument.Parse(XML_EMPTYENVIRONMENTS));
			});

			Assert.Equal("parameterXml", exception.ParamName);
		}

		[Fact]
		public void BuildParameterList_WithNullEnvironmentXmlDoc_ThrowsArgumentNullException()
		{
			var exception = Assert.Throws<ArgumentNullException>(
			delegate
			{
				new ParameterListBuilder().BuildParameterList(XDocument.Parse(XML_EMPTYPARAMETERS), null);
			});

			Assert.Equal("environmentXml", exception.ParamName);
		}

		[Fact]
		public void BuildParameterList_WithEmptyParametersElement_ReturnsEmptyParameterList()
		{
			var actual = new ParameterListBuilder().BuildParameterList(
				XDocument.Parse(XML_EMPTYPARAMETERS), XDocument.Parse(XML_EMPTYENVIRONMENTS));

			Assert.NotNull(actual);
			Assert.Equal(0, actual.Count);
		}

		[Fact]
		public void BuildParameterList_OnlyReturnsParametersWithXmlFileParameterEntryElements()
		{
			var actual = new ParameterListBuilder().BuildParameterList(
				XDocument.Parse(
					"<parameters>" +
						"<parameter name=\"1\"></parameter>" +
						"<parameter name=\"2\"><parameterEntry kind=\"ProviderPath\"/></parameter>" +
						"<parameter name=\"3\" tags=\"aaa\" description=\"bbb\"><parameterEntry kind=\"XmlFile\"/></parameter>" +
					"</parameters>"), 
				XDocument.Parse(XML_EMPTYENVIRONMENTS)
			);

			Assert.NotNull(actual);
			Assert.Equal(1, actual.Count);
			Assert.Equal("3", actual[0].Name);
			Assert.Equal("aaa", actual[0].Tags);
			Assert.Equal("bbb", actual[0].Description);
		}

		[Fact]
		public void BuildParameterList_ReturnsParametersDefaultValueAsValueIfNoMatchingEnvironmentValue()
		{
			var actual = new ParameterListBuilder().BuildParameterList(
				XDocument.Parse(
					"<parameters>" +
						"<parameter name=\"2\" defaultValue=\"ddd\"><parameterEntry kind=\"XmlFile\"/></parameter>" +
						"<parameter name=\"3\" defaultValue=\"\"><parameterEntry kind=\"XmlFile\"/></parameter>" +
					"</parameters>"),
				XDocument.Parse(XML_EMPTYENVIRONMENTS)
			);

			Assert.NotNull(actual);
			Assert.Equal(2, actual.Count);
			Assert.Equal("2", actual[0].Name);
			Assert.Equal("ddd", actual[0].Value);
			Assert.Equal("ddd", actual[0].DefaultValue);
			Assert.Equal("3", actual[1].Name);
			Assert.Equal("", actual[1].Value);
			Assert.Equal("", actual[1].DefaultValue);
		}

		[Fact]
		public void BuildParameterList_UsesMatchAttributeFromParameterEntryElement()
		{
			var actual = new ParameterListBuilder().BuildParameterList(
				XDocument.Parse(
					"<parameters>" +
						"<parameter name=\"3\"><parameterEntry kind=\"XmlFile\" match=\"/aaa/bbb\"/></parameter>" +
					"</parameters>"),
				XDocument.Parse(XML_EMPTYENVIRONMENTS)
			);

			Assert.NotNull(actual);
			Assert.Equal(1, actual.Count);
			Assert.Equal("3", actual[0].Name);
			Assert.Equal("/aaa/bbb", actual[0].Match);
		}

		[Fact]
		public void BuildParameterList_ReturnsEnvironmentValueAsParameterValueMatchedByName()
		{
			var actual = new ParameterListBuilder().BuildParameterList(
				XDocument.Parse(
					"<parameters>" +
						"<parameter name=\"2\" defaultValue=\"\"><parameterEntry kind=\"XmlFile\"/></parameter>" +
						"<parameter name=\"3\" defaultValue=\"aaa\"><parameterEntry kind=\"XmlFile\"/></parameter>" +
					"</parameters>"),
				XDocument.Parse(
					"<parameters>" +
						"<setParameter name=\"2\" value=\"ddd\"/>" +
						"<setParameter name=\"3\" value=\"\"/>" +
					"</parameters>"
				)
			);

			Assert.NotNull(actual);
			Assert.Equal(2, actual.Count);
			Assert.Equal("2", actual[0].Name);
			Assert.Equal("ddd", actual[0].Value);
			Assert.Equal("", actual[0].DefaultValue);
			Assert.Equal("3", actual[1].Name);
			Assert.Equal("", actual[1].Value);
			Assert.Equal("aaa", actual[1].DefaultValue);
		}
    }
}
